﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

/// <summary>
/// 日志级别枚举
/// </summary>
public enum LogLevel
{
    Trace = 0,
    Debug = 1,
    Info = 2,
    Warn = 3,
    Error = 4,
    Critical = 5
}

/// <summary>
/// 静态日志工具类 - 支持按日期自动创建日志文件，控制台输出，异常处理等功能
/// </summary>
public static class Logger
{
    private static string _currentLogDate;
    private static readonly object _lockObject = new object();
    private static string _logDirectory = "logs";
    private static LogLevel _minLogLevel = LogLevel.Debug;
    private static StreamWriter _currentWriter;
    private static readonly ConcurrentQueue<string> _logQueue = new ConcurrentQueue<string>();
    private static volatile bool _isRunning = true;
    private static Thread _logThread;

    /// <summary>
    /// 静态构造函数，初始化日志系统
    /// </summary>
    static Logger()
    {
        InitializeLogger();
        StartLogThread();

        // 注册应用程序退出事件
        AppDomain.CurrentDomain.ProcessExit += (s, e) => Shutdown();
        AppDomain.CurrentDomain.DomainUnload += (s, e) => Shutdown();
    }

    /// <summary>
    /// 初始化日志系统
    /// </summary>
    private static void InitializeLogger()
    {
        lock (_lockObject)
        {
            try
            {
                // 创建日志目录
                if (!Directory.Exists(_logDirectory))
                {
                    Directory.CreateDirectory(_logDirectory);
                    Console.WriteLine($"[Logger] 创建日志目录: {Path.GetFullPath(_logDirectory)}");
                }

                // 获取当前日期
                _currentLogDate = DateTime.Now.ToString("yyyyMMdd");

                // 关闭之前的文件流
                _currentWriter?.Close();
                _currentWriter?.Dispose();

                // 创建新的文件流
                string logFilePath = GetCurrentLogFilePath();
                _currentWriter = new StreamWriter(logFilePath, true, Encoding.UTF8)
                {
                    AutoFlush = true
                };

                // 如果是新文件，写入文件头
                if (new FileInfo(logFilePath).Length == 0)
                {
                    WriteFileHeader();
                }

                WriteToFile($"{GetTimestamp()} [INFO ] Logger - 日志系统初始化完成");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"[Logger] 初始化失败: {ex.Message}");
            }
        }
    }

    /// <summary>
    /// 启动日志写入线程
    /// </summary>
    private static void StartLogThread()
    {
        _logThread = new Thread(ProcessLogQueue)
        {
            Name = "LogWriterThread",
            IsBackground = true
        };
        _logThread.Start();
    }

    /// <summary>
    /// 处理日志队列
    /// </summary>
    private static void ProcessLogQueue()
    {
        while (_isRunning)
        {
            try
            {
                if (_logQueue.TryDequeue(out string logEntry))
                {
                    WriteToFile(logEntry);
                }
                else
                {
                    Thread.Sleep(10); // 队列为空时短暂休眠
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"[Logger] 日志写入线程错误: {ex.Message}");
            }
        }

        // 退出前写入所有剩余日志
        while (_logQueue.TryDequeue(out string logEntry))
        {
            WriteToFile(logEntry);
        }
    }

    /// <summary>
    /// 写入文件头信息
    /// </summary>
    private static void WriteFileHeader()
    {
        var header = new StringBuilder();
        header.AppendLine("=== 应用程序日志 ===");
        header.AppendLine($"创建时间: {DateTime.Now:yyyy-MM-dd HH:mm:ss}");
        header.AppendLine($"日志文件: {GetCurrentLogFilePath()}");
        header.AppendLine($"运行机器: {Environment.MachineName}");
        header.AppendLine($".NET 版本: {Environment.Version}");
        header.AppendLine($"操作系统: {Environment.OSVersion}");
        header.AppendLine();

        _currentWriter.Write(header.ToString());
    }

    /// <summary>
    /// 获取当前日志文件路径
    /// </summary>
    private static string GetCurrentLogFilePath()
    {
        return Path.Combine(_logDirectory, $"Upapp_{_currentLogDate}.log");
    }

    /// <summary>
    /// 获取时间戳
    /// </summary>
    private static string GetTimestamp()
    {
        return DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
    }

    /// <summary>
    /// 检查是否需要切换日志文件（日期变化）
    /// </summary>
    private static void CheckDateChange()
    {
        var today = DateTime.Now.ToString("yyyyMMdd");
        if (_currentLogDate != today)
        {
            lock (_lockObject)
            {
                if (_currentLogDate != today) // 双重检查
                {
                    _currentLogDate = today;
                    var message = $"{GetTimestamp()} [INFO ] Logger - 检测到日期变化，创建新的日志文件: {GetCurrentLogFilePath()}";
                    _logQueue.Enqueue(message);
                    InitializeLogger(); // 重新初始化日志器
                }
            }
        }
    }

    /// <summary>
    /// 写入日志到文件
    /// </summary>
    private static void WriteToFile(string logEntry)
    {
        lock (_lockObject)
        {
            try
            {
                _currentWriter?.WriteLine(logEntry);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"[Logger] 写入文件失败: {ex.Message}");
            }
        }
    }

    /// <summary>
    /// 内部日志记录方法
    /// </summary>
    private static void LogInternal(LogLevel level, string message, Exception exception = null)
    {
        if (level < _minLogLevel) return;

        CheckDateChange();

        var logEntry = $"{GetTimestamp()} [{GetLogLevelString(level)}] {message}";

        // 如果有异常信息，追加详细信息
        if (exception != null)
        {
            logEntry += $"{Environment.NewLine}异常详情: {exception}";
        }

        // 输出到控制台（带颜色）
        WriteToConsole(level, logEntry);

        // 添加到日志队列
        _logQueue.Enqueue(logEntry);
    }

    /// <summary>
    /// 输出到控制台（带颜色）
    /// </summary>
    private static void WriteToConsole(LogLevel level, string message)
    {
        var originalColor = Console.ForegroundColor;

        try
        {
            Console.ForegroundColor = GetConsoleColor(level);
            Console.WriteLine(message);
            Console.ForegroundColor = originalColor;
        }
        catch
        {
            // 控制台不可用时忽略错误
        }
    }

    /// <summary>
    /// 获取日志级别的字符串表示
    /// </summary>
    private static string GetLogLevelString(LogLevel level)
    {
        switch (level)
        {
            case LogLevel.Trace: return "TRACE";
            case LogLevel.Debug: return "DEBUG";
            case LogLevel.Info: return "INFO ";
            case LogLevel.Warn: return "WARN ";
            case LogLevel.Error: return "ERROR";
            case LogLevel.Critical: return "FATAL";
            default: return "UNKNOWN";
        }
    }

    /// <summary>
    /// 获取控制台颜色
    /// </summary>
    private static ConsoleColor GetConsoleColor(LogLevel level)
    {
        switch (level)
        {
            case LogLevel.Trace: return ConsoleColor.Gray;
            case LogLevel.Debug: return ConsoleColor.DarkGray;
            case LogLevel.Info: return ConsoleColor.White;
            case LogLevel.Warn: return ConsoleColor.Yellow;
            case LogLevel.Error: return ConsoleColor.Red;
            case LogLevel.Critical: return ConsoleColor.DarkRed;
            default: return ConsoleColor.White;
        }
    }

    #region 配置方法

    /// <summary>
    /// 设置日志目录
    /// </summary>
    public static void SetLogDirectory(string directory)
    {
        lock (_lockObject)
        {
            _logDirectory = directory;
            InitializeLogger();
        }
    }

    /// <summary>
    /// 设置最低日志级别
    /// </summary>
    public static void SetMinLogLevel(LogLevel level)
    {
        _minLogLevel = level;
    }

    #endregion

    #region 公共日志方法

    /// <summary>
    /// 记录跟踪信息（最详细的日志）
    /// </summary>
    public static void Trace(string message)
    {
        LogInternal(LogLevel.Trace, message);
    }

    /// <summary>
    /// 记录跟踪信息（带格式化）
    /// </summary>
    public static void Trace(string format, params object[] args)
    {
        LogInternal(LogLevel.Trace, string.Format(format, args));
    }

    /// <summary>
    /// 记录调试信息
    /// </summary>
    public static void Debug(string message)
    {
        LogInternal(LogLevel.Debug, message);
    }

    /// <summary>
    /// 记录调试信息（带格式化）
    /// </summary>
    public static void Debug(string format, params object[] args)
    {
        LogInternal(LogLevel.Debug, string.Format(format, args));
    }

    /// <summary>
    /// 记录常规信息
    /// </summary>
    public static void Info(string message)
    {
        LogInternal(LogLevel.Info, message);
    }

    /// <summary>
    /// 记录常规信息（带格式化）
    /// </summary>
    public static void Info(string format, params object[] args)
    {
        LogInternal(LogLevel.Info, string.Format(format, args));
    }

    /// <summary>
    /// 记录警告信息
    /// </summary>
    public static void Warn(string message)
    {
        LogInternal(LogLevel.Warn, message);
    }

    /// <summary>
    /// 记录警告信息（带格式化）
    /// </summary>
    public static void Warn(string format, params object[] args)
    {
        LogInternal(LogLevel.Warn, string.Format(format, args));
    }

    /// <summary>
    /// 记录错误信息
    /// </summary>
    public static void Error(string message)
    {
        LogInternal(LogLevel.Error, message);
    }

    /// <summary>
    /// 记录错误信息（带格式化）
    /// </summary>
    public static void Error(string format, params object[] args)
    {
        LogInternal(LogLevel.Error, string.Format(format, args));
    }

    /// <summary>
    /// 记录异常信息
    /// </summary>
    public static void Error(Exception exception, string message = null)
    {
        if (string.IsNullOrEmpty(message))
        {
            LogInternal(LogLevel.Error, "发生异常", exception);
        }
        else
        {
            LogInternal(LogLevel.Error, message, exception);
        }
    }

    /// <summary>
    /// 记录严重错误信息
    /// </summary>
    public static void Critical(string message)
    {
        LogInternal(LogLevel.Critical, message);
    }

    /// <summary>
    /// 记录严重错误信息（带格式化）
    /// </summary>
    public static void Critical(string format, params object[] args)
    {
        LogInternal(LogLevel.Critical, string.Format(format, args));
    }

    /// <summary>
    /// 记录严重异常信息
    /// </summary>
    public static void Critical(Exception exception, string message = null)
    {
        if (string.IsNullOrEmpty(message))
        {
            LogInternal(LogLevel.Critical, "发生严重异常", exception);
        }
        else
        {
            LogInternal(LogLevel.Critical, message, exception);
        }
    }

    #endregion

    #region 便捷方法

    /// <summary>
    /// 记录方法进入
    /// </summary>
    public static void Enter(string methodName, params object[] parameters)
    {
        var paramStr = parameters.Length > 0 ? $"参数: {string.Join(", ", parameters)}" : "无参数";
        Info($"→ 进入方法: {methodName} - {paramStr}");
    }

    /// <summary>
    /// 记录方法退出
    /// </summary>
    public static void Exit(string methodName, object result = null)
    {
        var resultStr = result != null ? $"结果: {result}" : "无返回值";
        Info($"← 退出方法: {methodName} - {resultStr}");
    }

    /// <summary>
    /// 记录操作开始
    /// </summary>
    public static void StartOperation(string operation)
    {
        Info($"🚀 开始操作: {operation}");
    }

    /// <summary>
    /// 记录操作完成
    /// </summary>
    public static void CompleteOperation(string operation)
    {
        Info($"✅ 操作完成: {operation}");
    }

    /// <summary>
    /// 记录操作失败
    /// </summary>
    public static void FailOperation(string operation, Exception ex = null)
    {
        if (ex != null)
        {
            Error(ex, $"❌ 操作失败: {operation}");
        }
        else
        {
            Error($"❌ 操作失败: {operation}");
        }
    }

    /// <summary>
    /// 记录性能信息
    /// </summary>
    public static void Performance(string operation, long elapsedMilliseconds)
    {
        Info($"⏱️ 性能统计 - {operation}: {elapsedMilliseconds}ms");
    }

    #endregion

    /// <summary>
    /// 获取当前日志文件信息
    /// </summary>
    public static void GetLogInfo()
    {
        var logFile = GetCurrentLogFilePath();
        if (File.Exists(logFile))
        {
            var fileInfo = new FileInfo(logFile);
            Info($"📊 日志文件信息 - 路径: {logFile}, 大小: {fileInfo.Length / 1024.0:F2} KB");
        }
        else
        {
            Info("📊 日志文件尚未创建");
        }
    }

    /// <summary>
    /// 关闭日志系统
    /// </summary>
    public static void Shutdown()
    {
        _isRunning = false;

        // 等待日志线程结束
        _logThread?.Join(1000);

        lock (_lockObject)
        {
            _currentWriter?.Close();
            _currentWriter?.Dispose();
            _currentWriter = null;
        }

        Info("日志系统已关闭");
    }
}
